package main

import (
	"errors"
	"fmt"
	"reflect"
)

func main() {
	//不支持有默认值的传递，调用的必须按照签名的顺序传递指定类型。go语言的参数定义不是很灵活
	A(1, 2)

	a := 100
	fmt.Println(&a)
	p := &a
	fmt.Printf("%p, %v\n", &p, p)

	/*
		p与test函数的参数x都指向a的地址，所以他俩值是a的地址，但他俩是不同的（地址不同，运行结果可见）
		若在其他语言如java，则p与x应为相同的
	*/
	test(p)

	//数组是需要指定个数的，而切片则不需要。数组赋值也可是使用如下方式，忽略元素个数，使用“...”代替
	var a1 []int = []int{1, 2, 3, 4}
	test2("a", a1...)
	test2("b", a1[:]...)

	test2("c", 1, 2, 3, 4, 5)

	fmt.Println(reflect.TypeOf(a1))
	b := a1[:]
	fmt.Println(reflect.TypeOf(b))

	c, err := test3(1)
	fmt.Println(c, err)
}

//go的函数传值还是传指针？传值！go语言一切函数参数都是传值的
func A(a int, b int) {
	//a:=10   函数内部的变量名称不能与参数名相同
	a1 := 100
	fmt.Println(a, b)
	fmt.Println(a1)
}

func test(x *int) {
	fmt.Printf("%p, %v\n", &x, x)
}

func test2(s string, a ...int) { //a是切片slice。切片可变化，数组是固定的。  不定长的参数只能放在最后一个位置。
	fmt.Printf("%T, %v\n", a, a)
}

//go语言的返回值，返回值类型卸载最后。可以返回多个结果
func test3(a int) (int, error) {
	b := a + 3
	return b, errors.New("error")
}

//go语言可以给返回值定义名称，其也属于函数内部的局部变量，所以函数内部不能有变量名相同的
func test4(a int) (age int, name string) {
	b := a + 4
	return b, "sldkfj"
}
